﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;

namespace Team6_Algorithms.Operations
{
    /// <summary>
    /// Made by Pascal Schotman && Dylan Snel
    /// Function for cropping the image.
    /// </summary>
    public static class Cropper
    {
        /// <summary>
        /// Crop the given image at the given points
        /// </summary>
        /// <param name="srcBitmap">the inputimage to be cropped</param>
        /// <param name="xMin">the minimal x point from where to crop</param>
        /// <param name="xMax">the maximal x point from where to crop</param>
        /// <param name="yMin">the minimal y point from where to crop</param>
        /// <param name="yMax">the maximal y point from where to crop</param>
        /// <returns>Cropped bitmap</returns>
        public static Bitmap crop(this Bitmap srcBitmap, int xMin, int xMax, int yMin, int yMax)
        {
            Rectangle cropArea = new Rectangle(xMin, yMin, (xMax - xMin), (yMax - yMin));
            Bitmap targetBitmap = srcBitmap.Clone(cropArea, srcBitmap.PixelFormat);
            return targetBitmap;
        }
        
        /// <summary>
        /// Determines the area where to crop ( need to be a binairy image, will crop from the min x/y to max x/y
        /// </summary>
        /// <param name="B">The input image to be cropped</param>
        /// <returns>The cropped bitmap</returns>
        public static Bitmap cropBlack(this Bitmap B)
        {
            int pointerShift;
            Bitmap bSrc = (Bitmap)B.Clone();
            BitmapData BmData = B.LockBits(new Rectangle(0, 0, B.Width, B.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            int stride = BmData.Stride;
            int nWidth = B.Width;
            int nHeight = B.Height;


            System.IntPtr Scan0 = BmData.Scan0;

            unsafe
            {
                byte* gScan0 = (byte*)(void*)Scan0;
                int xMin = B.Width;
                int yMin = B.Height;
                int xMax = 0;
                int yMax = 0;
                if (gScan0[0] != gScan0[1])
                    throw new Exception("ImageNotBlackWhiteException");

                int x = 0, y = 0;
                for (y = 0; y < nHeight; y++)
                {
                    for (x = 0; x < nWidth; x++)
                    {
                        pointerShift = (y * stride) + (x * 3);
                        if (gScan0[pointerShift] <= 128)
                        {
                            if (x < xMin)
                                xMin = x;
                            if (y < yMin)
                                yMin = y;
                            if (x > xMax)
                                xMax = x;
                            if (y > yMax)
                                yMax = y;
                        }
                    }
                }
                B.UnlockBits(BmData);

                return B.crop(xMin, xMax, yMin, yMax);

            }
        }

        /// <summary>
        /// Adds a white border to the image
        /// </summary>
        /// <param name="srcBitmap">The input image</param>
        /// <param name="edge">the length of the border</param>
        /// <returns>the image with the border</returns>
        public static Bitmap addWhiteEdge(this Bitmap srcBitmap, int edge)
        {
            Bitmap returnBitmap = new Bitmap(srcBitmap.Width + (edge*2), srcBitmap.Height + (edge*2));
            Rectangle srcRegion = new Rectangle(0,0, returnBitmap.Width, returnBitmap.Height);
            Graphics g = Graphics.FromImage(returnBitmap);
            SolidBrush myBrush = new SolidBrush(Color.White);
            g.FillRectangle(myBrush, srcRegion);
            g.Dispose();
            Rectangle retRegion = new Rectangle(edge,edge, srcBitmap.Width, srcBitmap.Height);
            Graphics gr = Graphics.FromImage(returnBitmap);
            gr.DrawImage(srcBitmap, retRegion, srcRegion, GraphicsUnit.Pixel);
            gr.Dispose();
            return returnBitmap;
        }
    }
}
